package com.easyboot.web.monitor.jobutils;

import com.easyboot.utils.log.LoggerHelper;
import com.easyboot.constant.ScheduleConstants;
import com.easyboot.framework.exception.EasyException;
import com.easyboot.framework.utils.spring.SpringUtils;
import com.easyboot.web.monitor.domain.MonitorJob;
import org.quartz.*;
import org.springframework.context.ApplicationContext;


/**
 * @author yushuo
 * @className
 * @descripton TODO
 * @date 2021/6/3 15:55
 **/
public class ScheduleUtils {

    /**
     * 构建任务触发对象
     */
    public static TriggerKey getTriggerKey(Long jobId, String jobGroup) {
        return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
    }

    /**
     * 构建任务键对象
     */
    public static JobKey getJobKey(Long jobId, String jobGroup){
        return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
    }

    /*
    *
     * @author yushuo
     * @description 触发执行一次任务
     * @date 15:25 2021/6/23
     * @param [scheduler, job]
     * @return void
    **/
    public static void runJob(Scheduler scheduler,MonitorJob job) throws SchedulerException{
        JobKey jobKey=JobKey.jobKey(job.getInvokeTarget(), job.getJobGroup());
        if (scheduler.checkExists(jobKey))
        {
            scheduler.triggerJob(jobKey);
        }
    }
    /**
     * @author yushuo
     * @description暂停任务
     * @date 14:51 2021/6/23
     * @param [scheduler, job]
     * @return void
    **/
    public static void pauseJob(Scheduler scheduler,MonitorJob job) throws SchedulerException{
        JobKey jobKey=JobKey.jobKey(job.getInvokeTarget(), job.getJobGroup());
        if (scheduler.checkExists(jobKey))
        {
            scheduler.pauseJob(jobKey);
        }
    }
    /**
     * @author yushuo
     * @description 恢复任务
     * @date 14:51 2021/6/23
     * @param [scheduler, job]
     * @return void
     **/
    public static void resumeJob(Scheduler scheduler,MonitorJob job) throws SchedulerException{
        JobKey jobKey=JobKey.jobKey(job.getInvokeTarget(), job.getJobGroup());
        if (scheduler.checkExists(jobKey))
        {
            scheduler.resumeJob(jobKey);
        }else{
            createScheduleJob(scheduler,job);
        }
    }

    /**
    *
     * @author yushuo
     * @description 删除任务
     * @date 17:02 2021/6/22
     * @param [scheduler, job]
     * @return boolean
    **/
    public static boolean deleteJob(Scheduler scheduler,MonitorJob job){
        JobKey jobKey=JobKey.jobKey(job.getInvokeTarget(), job.getJobGroup());
        try {
            if (scheduler.checkExists(jobKey))
            {
                // 防止创建时存在数据问题 先移除，然后在执行创建操作
                scheduler.deleteJob(jobKey);
            }
            return true;
        }catch (Exception ex){
            LoggerHelper.error(ex.getMessage());
        }
            return  false;
    }
    /**
     * 创建定时任务
     */
    public static void createScheduleJob(Scheduler scheduler, MonitorJob job) throws SchedulerException,EasyException{
        ApplicationContext applicationContext= SpringUtils.getApplicationContext();
        // Class<? extends Job> jobClass = (Class<? extends Job>) SpringUtils.getBean(job.getInvokeTarget()).getClass();
         Class<? extends Job> jobClass = (Class<? extends Job>) applicationContext.getBean(job.getInvokeTarget()).getClass();
        // 构建job信息
        Long jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        // 创建jobDetail实例，绑定Job实现类
        // 指明job的名称，所在组的名称，以及绑定job类
        JobKey jobKey=JobKey.jobKey(job.getInvokeTarget(), jobGroup);
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).build();
         jobDetail.isConcurrentExectionDisallowed();
        // 表达式调度构建器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
        cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);

        // 按新的cronExpression表达式构建一个新的trigger
        TriggerKey triggerKey= TriggerKey.triggerKey(job.getInvokeTarget(),jobGroup);
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
                   .withSchedule(cronScheduleBuilder).build();
        // 放入参数，运行时的方法可以获取
        jobDetail.getJobDataMap().put("jobId", job.getJobId());
        jobDetail.getJobDataMap().put("easyboot","hello from context param");

        // 判断是否存在
        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        JobListener listener = new EasyQuartzJobListener();
        //Matcher<JobKey> matcher = KeyMatcher.keyEquals(jobKey);
        scheduler.getListenerManager().addJobListener(listener);
        scheduler.scheduleJob(jobDetail, trigger);

        // 暂停任务
        if (job.getJobStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) {
            scheduler.pauseJob(jobKey);
        }
    }

    /**
     * 设置定时任务策略
     */
    public static CronScheduleBuilder handleCronScheduleMisfirePolicy(MonitorJob job, CronScheduleBuilder cb)
            throws EasyException {
        switch (job.getMisfirePolicy()) {
            case ScheduleConstants.MISFIRE_DEFAULT:
                return cb;
            case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
                return cb.withMisfireHandlingInstructionIgnoreMisfires();
            case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
                return cb.withMisfireHandlingInstructionFireAndProceed();
            case ScheduleConstants.MISFIRE_DO_NOTHING:
                return cb.withMisfireHandlingInstructionDoNothing();
            default:
                throw new EasyException("The task misfire policy '" + job.getMisfirePolicy() + "' cannot be used in cron schedule tasks");
        }
    }
}